package com.GroupSix.service;

import com.GroupSix.dao.*;
import com.GroupSix.entity.ExamPaperEntity;
import com.GroupSix.entity.PaperGenerationRule;
import com.GroupSix.entity.QuestionBankEntity;
import com.GroupSix.entity.TeacherEntity;
import com.GroupSix.vo.PaperGenerationRuleVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service("ExamPaperService")
public class ExamPaperServiceImpl extends ServiceImpl<ExamPaperDao, ExamPaperEntity>
        implements ExamPaperService {
    //注入Dao层
    @Autowired
    private PaperGenerationRuleDao ruleDao;
    @Autowired
    private QuestionBankDao questionBankDao;
    @Autowired
    private DictDao dictDao;
    @Autowired
    private ExamPaperDao examPaperDao;
    @Autowired
    private TeacherDao teacherDao;

    //增
    @Override
    public Integer add(ExamPaperEntity examPaperEntity) {
        examPaperEntity.setCreateTime(LocalDateTime.now());
        examPaperEntity.setUpdateTime(LocalDateTime.now());
        return examPaperDao.insert(examPaperEntity);
    }

    //删
    @Override
    public Integer delete(int id) {
        return examPaperDao.deleteById(id);
    }

    //查
    @Override
    public ExamPaperEntity find(int id) {
        return examPaperDao.selectById(id);
    }

    //改
    @Override
    public Integer update(ExamPaperEntity examPaperEntity) {
        examPaperEntity.setUpdateTime(LocalDateTime.now());
        return examPaperDao.updateById(examPaperEntity);
    }

    //分页查询
    @Override
    public IPage<ExamPaperEntity> list(ExamPaperEntity examPaperEntity, Integer pageNo, Integer pageSize) {
        LambdaQueryWrapper<ExamPaperEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ObjectUtils.isNotEmpty(examPaperEntity.getId()), ExamPaperEntity::getId, examPaperEntity.getId());

        int currentPage = 1;
        int limit = 10;
        if (pageNo != null && pageNo > 0) {
            currentPage = pageNo;
        }
        if (pageSize != null && pageSize > 0) {
            limit = pageSize;
        }

        IPage<ExamPaperEntity> page = Page.of(currentPage, limit);

        return examPaperDao.selectPage(page, wrapper);
    }

    //根据试题生成规则生成试卷
    //形参：规则id、教师账号、试卷类型（AB卷）
    @Override
    public ExamPaperEntity generateExamPaper(Long ruleId, Long teacherId, String type) {
        //获取规则
        PaperGenerationRule rule = ruleDao.selectById(ruleId);
        if (rule == null) {
            throw new RuntimeException("规则不存在，规则 ID：" + ruleId);
        }

        //封装规则
        PaperGenerationRuleVo ruleVo = toVo(rule);

        //根据规则获取符合条件的题目
        QueryWrapper<QuestionBankEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("qsknowledge", Arrays.asList(ruleVo.getKnowledgePoint()))      //匹配知识点
                .eq("qsdifficulty", ruleVo.getDifficultyLevel())        //匹配难易度
                .eq("qsis_active", 0);       //是否有效

        //根据知识点和难易度筛选后的题目列表
        List<QuestionBankEntity> questions = questionBankDao.selectList(queryWrapper);

        //为每个题型选择相应数量的题目
        // 使用流（Stream）对题目进行分组，以题型为键
        Map<Integer, List<QuestionBankEntity>> questionGroups = questions.stream()
                .collect(Collectors.groupingBy(QuestionBankEntity::getQstype));
        //用于存储最终被选中的题目
        List<QuestionBankEntity> selectedQuestions = new ArrayList<>();
        // 遍历规则中的题型和对应数量
        for (Map.Entry<Integer, Integer> entry : ruleVo.getQuestionTypeCount().entrySet()) {
            Integer questionType = entry.getKey();  // 获取题型
            Integer count = entry.getValue();       // 获取该题型需要选择的题目数量
            // 从分组中获取对应题型的题目列表
            List<QuestionBankEntity> typeQuestions = questionGroups.get(questionType);
            // 检查该题型的题目数量是否满足要求
            if (typeQuestions.size() >= count) {
                //题目数量足够时
                Collections.shuffle(typeQuestions);
                selectedQuestions.addAll(typeQuestions.subList(0, count));
            } else {
                // 题目数量不足时抛出异常
                throw new RuntimeException("题目数量不足，题型：" + questionType + ", 需要："
                        + count + ", 实际：" + typeQuestions.size());
            }
        }

        //生成题号数组
        Integer[] array = new Integer[selectedQuestions.size()];
        for (int i = 0; i < selectedQuestions.size(); i++) {
            QuestionBankEntity questionBankEntity = selectedQuestions.get(i);
            long temp = questionBankEntity.getId();
            array[i] = (int) temp;
        }

        //通过教师账号定位到教师信息
        LambdaQueryWrapper<TeacherEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(TeacherEntity::getTeacherId, teacherId);
        TeacherEntity teacher = teacherDao.selectOne(lambdaQueryWrapper);

        //返回试卷信息
        ExamPaperEntity examPaper = new ExamPaperEntity();
        examPaper.setPaperType(type);
        examPaper.setRuleId(ruleId);
        examPaper.setTeacherId(teacher.getId());
        examPaper.setPaperName(dictDao.selectById(ruleVo.getCourseId()).getDictName());
        examPaper.setQuestions(array);
        examPaper.setStartTime(ruleVo.getPaperStart());
        examPaper.setEndTime(ruleVo.getPaperStart().plusMinutes(ruleVo.getTimeLimit()));
        examPaper.setCreateTime(LocalDateTime.now());
        examPaper.setUpdateTime(LocalDateTime.now());
        examPaper.setIsActive(0);

        //保存试卷信息
        examPaperDao.insert(examPaper);

        //返回试卷的实体类
        return examPaper;
    }

    //封装规则
    private PaperGenerationRuleVo toVo(PaperGenerationRule rule) {
        PaperGenerationRuleVo vo = new PaperGenerationRuleVo();
        //将字符串反序列化为map集合
        String jsonString = rule.getQuestionTypeCount();
        ObjectMapper objectMapper = new ObjectMapper();
        Map<Integer, Integer> map = null;
        try {
            map = objectMapper.readValue(jsonString, new TypeReference<Map<Integer, Integer>>() {
            });
        } catch (IOException e) {
            //抛出运行时异常
            throw new RuntimeException("Error parsing JSON string to Map: " + jsonString, e);
        }

        //将rule的数据导入封装类
        vo.setQuestionTypeCount(map);
        vo.setId(rule.getId());
        vo.setCourseId(rule.getCourseId());
        vo.setKnowledgePoint(rule.getKnowledgePoint());
        vo.setScore(rule.getScore());
        vo.setDifficultyLevel(rule.getDifficultyLevel());
        vo.setPaperStart(rule.getPaperStart());
        vo.setIsActive(rule.getIsActive());
        vo.setTimeLimit(rule.getTimeLimit());

        return vo;
    }
}
